Skip to content

Leaning Weekly-2025-02-09

Chain-call delayed executor

链式调用和延迟执行【渡一教育】_哔哩哔哩_bilibili

ts
/**
 * 一个可以链式调用并添加延迟执行的方法
 * @author: Ruan Jiazhen
 * @date: 2025-02-04 18:11:14
 **/

/**
 * 一个可以链式调用并添加延迟执行的执行器
 */
interface ChainCallDelayedExecutor {
  /**
   * 添加一个任务到任务队列中
   * @param callback 任务函数
   */
  do: (callback: Function) => ChainCallDelayedExecutor;
  /**
   * 在前一个任务执行完毕后等待指定时间
   * @param delay 等待时间(毫秒)
   */
  wait: (delay: number) => ChainCallDelayedExecutor;
  /**
   * 在等待指定时间后执行前一个任务
   * @param delay 等待时间(毫秒)
   */
  waitFirst: (delay: number) => ChainCallDelayedExecutor;
  /**
   * 执行任务队列中的所有任务
   */
  execute: () => ChainCallDelayedExecutor;
}

export const main = () => {
  /**
   * 生成并返回一个 ChainCallDelayedExecutor 对象
   * @param name 传入的字符串
   */
  const generateExecutor = (name: string): ChainCallDelayedExecutor => {
    console.log(`generateExecutor: ${name}`);
    //  定义一个名为arrange的函数,接受一个字符串类型的参数name,并返回一个ChainCallDelayedExecutor类型的对象
    const tasks: Function[] = [];

    const executor: ChainCallDelayedExecutor = {
      do: function (callback: Function): ChainCallDelayedExecutor {
        tasks.push(callback);
        return executor;
      },
      wait: function (delay: number): ChainCallDelayedExecutor {
        tasks.push(() => new Promise((resolve) => setTimeout(resolve, delay)));
        return executor;
      },
      waitFirst: function (delay: number): ChainCallDelayedExecutor {
        tasks.unshift(
          () => new Promise((resolve) => setTimeout(resolve, delay)),
        );
        return executor;
      },
      execute: function (): ChainCallDelayedExecutor {
        (async () => {
          for (const task of tasks) {
            await task();
          }
          console.log('end', new Date().toLocaleTimeString());
        })();
        return executor;
      },
    };

    return executor;
  };

  const executor = generateExecutor('tasks');

  console.log('start', new Date().toLocaleTimeString());

  executor
    .do(() => console.log('first', new Date().toLocaleTimeString()))
    .wait(1000)
    .do(() => console.log('second', new Date().toLocaleTimeString()))
    .waitFirst(1000)
    .execute();
};

Taking the inverse of a type

never类型的妙用2【渡一教育】_哔哩哔哩_bilibili

ts
type BanType<T, U> = T extends U ? never : T;

const method = <T>(a: BanType<T, number>) => a;

method('test');
method({});
method(1); // Error: Argument of type '1' is not assignable to parameter of type 'never'.

A task executor that can be paused and resumed

任务队列的中断和恢复【渡一教育】_哔哩哔哩_bilibili

ts
/**
 * A task execute process can be paused and resumed.
 * @author: Ruan Jiazhen
 * @date: 2025-02-04 19:09:34
 **/

interface ProcessTasks {
  (...arg: Function[]): {
    start: () => Promise<any[] | undefined>;
    pause: () => void;
  };
}

const processTasks: ProcessTasks = function (...arg: Function[]) {
  let isRunning = false;
  let nextTaskIndex = 0;

  const results: any[] = [];

  const start = async () => {
    if (isRunning) return;
    isRunning = true;

    while (isRunning && nextTaskIndex < arg.length) {
      const task = arg[nextTaskIndex];
      const result = await task();
      results.push(result);
      nextTaskIndex++;
    }

    if (!isRunning) {
      console.log('task paused on index', nextTaskIndex - 1);
      return;
    }

    console.log('all tasks finished');
    return results;
  };

  const pause = () => {
    isRunning = false;
  };

  return {
    start,
    pause,
  };
};

export const main = () => {
  const tasks = [
    async () => {
      console.log('task 1 finished');
      return 1;
    },
    async () => {
      await new Promise((resolve) => setTimeout(resolve, 2000));
      console.log('task 2 finished');
      return 2;
    },
    async () => {
      await new Promise((resolve) => setTimeout(resolve, 3000));
      console.log('task 3 finished');
      return 3;
    },
  ];

  const { start, pause } = processTasks(...tasks);

  start().then((res) => {
    console.log('1 start res', res);
  });

  setTimeout(() => {
    console.log('try to pause');
    pause();
  }, 1000);

  setTimeout(() => {
    console.log('try to resume');
    start().then((res) => {
      console.log('2 start res', res);
    });
  }, 3000);
};